package com.abso.mp3tunes.locker.ui.actions;

import java.lang.reflect.InvocationTargetException;
import java.util.List;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.widgets.Shell;

import com.abso.mp3tunes.locker.core.LockerServiceException;
import com.abso.mp3tunes.locker.core.data.Album;
import com.abso.mp3tunes.locker.core.data.Artist;
import com.abso.mp3tunes.locker.core.data.LockerDataUtils;
import com.abso.mp3tunes.locker.core.data.Track;
import com.abso.mp3tunes.locker.ui.LockerImages;
import com.abso.mp3tunes.locker.ui.LockerPlugin;
import com.abso.mp3tunes.locker.ui.dialogs.PlaylistNameValidator;
import com.abso.mp3tunes.locker.ui.viewers.LockerViewer;
import com.abso.mp3tunes.locker.ui.viewers.PlaylistViewer;
import com.abso.mp3tunes.locker.ui.views.LockerBrowserView;

/**
 * Action able to adds a set of tracks to a new playlist.
 */
public class AddToNewPlaylistAction extends AbstractLockerViewerAction {

	/** The selected elements. */
	private List elements;

	/**
	 * Constructs a new action.
	 * 
	 * @param lockerViewer
	 *            the Locker tree viewer.
	 */
	public AddToNewPlaylistAction(LockerViewer lockerViewer) {
		super("Add to New Playlist...", LockerImages
				.getDescriptor(LockerImages.ADD_TO_PLAYLIST), lockerViewer);
	}

	/**
	 * Sets the current selection.
	 * 
	 * @param elements
	 *            the selected elements.
	 */
	public void setSelectedElements(List elements) {
		this.elements = elements;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jface.action.Action#run()
	 */
	public void run() {
		final InputDialog inputDialog = new InputDialog(LockerPlugin
				.getActiveWorkbenchShell(), "New Playlist",
				"Insert the name of the new playlist:", getPlaylistTitle(),
				new PlaylistNameValidator(null));
		if (inputDialog.open() != Window.OK) {
			return;
		}
		IRunnableWithProgress runnable = new IRunnableWithProgress() {
			public void run(IProgressMonitor monitor)
					throws InvocationTargetException, InterruptedException {
				Track[] tracksToAdd = unwrapTracks(elements, monitor);
				if (tracksToAdd == null) {
					return;
				}
				try {
					LockerPlugin.getDefault().getLockerService()
							.createPlaylist(inputDialog.getValue(),
									LockerDataUtils.getTrackKeys(tracksToAdd));
					getLockerViewer().getLockerBrowser().setViewerDirty(
							LockerBrowserView.PLAYLIST_MODE);
				} catch (LockerServiceException e) {
					showErrorDialog("Error", "Unable to create the playlist",
							"Error creating the playlist", e);
				}
				runUIAsync(new Runnable() {
					public void run() {
						if (getLockerViewer() instanceof PlaylistViewer) {
							getLockerViewer().setDirty();
							getLockerViewer().updateContent();
						}
					}
				});
			}
		};
		try {
			ProgressMonitorDialog dialog = new ProgressMonitorDialog(
					LockerPlugin.getActiveWorkbenchShell()) {
				protected void configureShell(final Shell shell) {
					super.configureShell(shell);
					shell.setText("Playlist Creation");
				}
			};
			dialog.run(true, true, runnable);
		} catch (InvocationTargetException e) {
		} catch (InterruptedException e) {
		}
	}

	/**
	 * Tries to guess a playlist title, based on the current selected elements.
	 * 
	 * @return the suggested playlist title.
	 */
	private String getPlaylistTitle() {
		if (elements.size() == 1) {
			Object elem = elements.get(0);
			if (elem instanceof Artist) {
				return ((Artist) elem).getName();
			} else if (elem instanceof Album) {
				Album album = (Album) elem;
				return album.getTitle() + " - " + album.getArtistName();
			} else if (elem instanceof Track) {
				return ((Track) elem).getTitle();
			}
		}
		return "New Playlist";
	}
}
